Skip to content

fix(rivetkit-core): gate startup until runtime is ready#4736

Closed
NathanFlurry wants to merge 1 commit into04-24-fix_sqlite_text_nul_roundtripfrom
04-24-fix_rivetkit-core_gate_startup_until_runtime_ready
Closed

fix(rivetkit-core): gate startup until runtime is ready#4736
NathanFlurry wants to merge 1 commit into04-24-fix_sqlite_text_nul_roundtripfrom
04-24-fix_rivetkit-core_gate_startup_until_runtime_ready

Conversation

@NathanFlurry
Copy link
Copy Markdown
Member

Description

Please include a summary of the changes and the related issue. Please also include relevant motivation and context.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Copy link
Copy Markdown
Member Author

NathanFlurry commented Apr 24, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@claude
Copy link
Copy Markdown

claude Bot commented Apr 24, 2026

Review of PR #4736: gate startup until runtime is ready

This is a solid and necessary fix. Gating active_actor on ctx.ready() closes a real race where a client request could arrive at an Active instance that has not completed its startup preamble, causing silent misbehavior. The TypeScript client changes are symmetrical and correctly extend the stale-identity retry logic to cover starting. A few things worth addressing:

ISSUES

  1. warn_work_sent_to_stopping_instance is the wrong diagnostic for the starting state

In rivetkit-rust/packages/rivetkit-core/src/registry/mod.rs (around the not-yet-ready Active instance branch), the code calls warn_work_sent_to_stopping_instance(active_actor).

This warning fires when an Active instance is not yet ready() -- meaning it is still starting, not stopping. The metric name inc_direct_subsystem_shutdown_warning and the log message work sent to stopping actor instance will mislead operators into thinking an actor is shutting down. This should use a distinct diagnostic path (e.g. warn_work_sent_to_starting_instance) or at minimum emit a different log message. The actual stopping path below uses the same helper correctly.

  1. actor.starting maps to 500 Internal Server Error from framework routes

In rivetkit-rust/packages/rivetkit-core/src/registry/http.rs (framework_error_status):

The function has no arm for (actor, starting), so it falls through to StatusCode::INTERNAL_SERVER_ERROR. The correct status for actor is still starting up, retry soon is 503 Service Unavailable. Consider adding (actor, starting) (and by symmetry stopping, destroying) mapping to StatusCode::SERVICE_UNAVAILABLE in framework_error_status.

  1. sendActionNow uses an inline setTimeout instead of waitForRetryWindow

In rivetkit-typescript/packages/rivetkit/src/client/actor-handle.ts (the starting/stopping retry branch inside sendActionNow): the inline 100ms delay is inconsistent with all other retry paths which call waitForRetryWindow(). Use the shared helper instead.

  1. isStaleResolvedActorError in actor-query.ts is missing destroying

In rivetkit-typescript/packages/rivetkit/src/client/actor-query.ts: The isStaleResolvedActorError function includes starting and stopping but not destroying. Meanwhile shouldRetryDynamicLifecycleError in actor-handle.ts includes destroying in its retry set. This means actor.destroying skips resolved-actor-ID invalidation. Since the PR explicitly updated both files to add starting, it would be consistent to add destroying to isStaleResolvedActorError in the same change.

  1. Missing trailing newline on actor.starting.json artifact

rivetkit-rust/engine/artifacts/errors/actor.starting.json is missing a trailing newline. All sibling files (actor.stopping.json, etc.) end with a newline.

MINOR OBSERVATIONS

  • sql-loader in pnpm-lock.yaml: The lockfile picks up @rivetkit/sql-loader@2.2.1 from npm for examples/kitchen-sink, while the workspace package is at 2.3.0-rc.4. Adding @rivetkit/sql-loader: workspace:* to root resolutions would align it with the other @rivetkit/* packages.

  • No new tests: The core behavioral change (rejecting active_actor when ready() is false) has no test coverage. A test in rivetkit-rust/packages/rivetkit-core/tests/ that calls active_actor on a mid-startup instance and asserts an actor.starting error would prevent regressions.

@NathanFlurry NathanFlurry force-pushed the 04-24-fix_sqlite_text_nul_roundtrip branch from 38f839d to e8072b7 Compare April 24, 2026 09:52
@NathanFlurry NathanFlurry force-pushed the 04-24-fix_rivetkit-core_gate_startup_until_runtime_ready branch from 6db71dc to e33e626 Compare April 24, 2026 09:52
@NathanFlurry NathanFlurry mentioned this pull request Apr 24, 2026
11 tasks
@NathanFlurry NathanFlurry force-pushed the 04-24-fix_rivetkit-core_gate_startup_until_runtime_ready branch from e33e626 to 06b3383 Compare April 24, 2026 09:54
@github-actions
Copy link
Copy Markdown
Contributor

Preview packages published to npm

Install with:

npm install rivetkit@pr-4736

All packages published as 0.0.0-pr.4736.ed96c00 with tag pr-4736.

Engine binary is shipped via @rivetkit/engine-cli on linux-x64-musl, linux-arm64-musl, darwin-x64, and darwin-arm64. Windows users should use the release installer or set RIVET_ENGINE_BINARY.

Docker images:

docker pull rivetdev/engine:slim-ed96c00
docker pull rivetdev/engine:full-ed96c00
Individual packages
npm install rivetkit@pr-4736
npm install @rivetkit/react@pr-4736
npm install @rivetkit/rivetkit-napi@pr-4736
npm install @rivetkit/workflow-engine@pr-4736

@NathanFlurry NathanFlurry force-pushed the 04-24-fix_sqlite_text_nul_roundtrip branch from e8072b7 to 4f00fb4 Compare April 24, 2026 10:19
@NathanFlurry NathanFlurry force-pushed the 04-24-fix_rivetkit-core_gate_startup_until_runtime_ready branch from 06b3383 to 49fed12 Compare April 24, 2026 10:19
@NathanFlurry NathanFlurry force-pushed the 04-24-fix_rivetkit-core_gate_startup_until_runtime_ready branch from 49fed12 to c4a5108 Compare April 24, 2026 10:32
@NathanFlurry NathanFlurry force-pushed the 04-24-fix_rivetkit-core_gate_startup_until_runtime_ready branch from c4a5108 to b563149 Compare April 24, 2026 11:48
@NathanFlurry NathanFlurry force-pushed the 04-24-fix_sqlite_text_nul_roundtrip branch from 3fd37c2 to 9fa17f8 Compare April 24, 2026 12:14
@NathanFlurry NathanFlurry force-pushed the 04-24-fix_rivetkit-core_gate_startup_until_runtime_ready branch from b563149 to 5aa18e8 Compare April 24, 2026 12:14
@NathanFlurry NathanFlurry force-pushed the 04-24-fix_rivetkit-core_gate_startup_until_runtime_ready branch from 5aa18e8 to d45b410 Compare April 24, 2026 12:32
@NathanFlurry
Copy link
Copy Markdown
Member Author

Landed in main via stack-merge fast-forward push. Commits are in main; closing to match.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant